// 版权归 Epic Games, Inc. 所有。保留所有权利。

#pragma once

#include "Components/GameStateComponent.h"
#include "ControlFlowNode.h"
#include "LoadingProcessInterface.h"

#include "LyraFrontendStateComponent.generated.h"

class FControlFlow;
class FString;
class FText;
class UObject;
struct FFrame;

enum class ECommonUserOnlineContext : uint8;
enum class ECommonUserPrivilege : uint8;
class UCommonActivatableWidget;
class UCommonUserInfo;
class ULyraExperienceDefinition;

UCLASS(Abstract)
class ULyraFrontendStateComponent : public UGameStateComponent, public ILoadingProcessInterface
{
	GENERATED_BODY()

public:

	ULyraFrontendStateComponent(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get()); // 构造函数

	//~UActorComponent 接口
	/**
	 * 当组件开始播放时调用
	 */
	virtual void BeginPlay() override;
	/**
	 * 当组件结束播放时调用
	 * @param EndPlayReason 结束播放的原因
	 */
	virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
	//~UActorComponent 接口结束

	//~ILoadingProcessInterface 接口
	/**
	 * 判断是否应显示加载屏幕
	 * @param OutReason 输出原因字符串
	 * @return 如果需要显示加载屏幕则返回 true，否则返回 false
	 */
	virtual bool ShouldShowLoadingScreen(FString& OutReason) const override;
	//~ILoadingProcessInterface 接口结束

private:
	/**
	 * 当经验加载完成时调用
	 * @param Experience 加载的经验定义
	 */
	void OnExperienceLoaded(const ULyraExperienceDefinition* Experience);

	UFUNCTION()
	/**
	 * 当用户初始化完成时调用
	 * @param UserInfo 用户信息
	 * @param bSuccess 是否成功
	 * @param Error 错误信息
	 * @param RequestedPrivilege 请求的权限
	 * @param OnlineContext 在线上下文
	 */
	void OnUserInitialized(const UCommonUserInfo* UserInfo, bool bSuccess, FText Error, ECommonUserPrivilege RequestedPrivilege, ECommonUserOnlineContext OnlineContext);

	/**
	 * 流程步骤：等待用户初始化
	 * @param SubFlow 子流程节点引用
	 */
	void FlowStep_WaitForUserInitialization(FControlFlowNodeRef SubFlow);
	/**
	 * 流程步骤：尝试显示 Press Start 屏幕
	 * @param SubFlow 子流程节点引用
	 */
	void FlowStep_TryShowPressStartScreen(FControlFlowNodeRef SubFlow);
	/**
	 * 流程步骤：尝试加入请求的会话
	 * @param SubFlow 子流程节点引用
	 */
	void FlowStep_TryJoinRequestedSession(FControlFlowNodeRef SubFlow);
	/**
	 * 流程步骤：尝试显示主屏幕
	 * @param SubFlow 子流程节点引用
	 */
	void FlowStep_TryShowMainScreen(FControlFlowNodeRef SubFlow);

	bool bShouldShowLoadingScreen = true; // 标记是否应显示加载屏幕

	UPROPERTY(EditAnywhere, Category = UI)
	TSoftClassPtr<UCommonActivatableWidget> PressStartScreenClass; // Press Start 屏幕类软引用

	UPROPERTY(EditAnywhere, Category = UI)
	TSoftClassPtr<UCommonActivatableWidget> MainScreenClass; // 主屏幕类软引用

	TSharedPtr<FControlFlow> FrontEndFlow; // 前端流程控制对象共享指针
	
	// 如果设置，则表示正在进行的 Press Start 屏幕任务
	FControlFlowNodePtr InProgressPressStartScreen; // 进行中的 Press Start 屏幕流程节点指针

	FDelegateHandle OnJoinSessionCompleteEventHandle; // 加入会话完成事件委托句柄
};